﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using Windows.Media.Playlists;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.FileProperties;
using Windows.Media;

// 빈 페이지 항목 템플릿에 대한 설명은 http://go.microsoft.com/fwlink/?LinkId=234238에 나와 있습니다.

namespace Hoons_Player
{
	/// <summary>
	/// 자체에서 사용하거나 프레임 내에서 탐색할 수 있는 빈 페이지입니다.
	/// </summary>
	public sealed partial class MainPage : Hoons_Player.Common.LayoutAwarePage
	{

		IReadOnlyList<StorageFile> files = null;
		StorageFile oSelectedStorageFile = null;

		public MainPage()
		{
			this.InitializeComponent();

			var _Colors = typeof(Colors).GetRuntimeProperties().Select((x, i) => new
			{
				Color = (Color)x.GetValue(null),
				Name = x.Name,
				Index = i,
				ColSpan = ColSpan(i),
				RowSpan = RowSpan(i)
			});
			//            this.DataContext = _Colors;
			this.DataContext = Music.Musics;

			//this.textBlock.DataContext = this.testData;

			//this.lv_news.DataContext = News.INSTANCE.GetNews("아이유", SEARCHENGINE.Naver);

			//Page Loaded
			this.Loaded += MainPage_Loaded;
		}

		void MainPage_Loaded(object sender, RoutedEventArgs e)
		{
			Player_Loaded(sender, e); //Player Load...
			PlayerEventSet(); //Player 관련 Button Event 정의
		}

		#region { Player 관련 }
		#region { 전역변수 }
		private DispatcherTimer _timer;
		private bool _sliderpressed = false;
		private double stepfrequency = -1;
		private string strStringFormat = "{0:00}:{1:00}";
		#endregion

		#region { Load }
		/// <summary>
		/// Player 관련 Event 정의
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void Player_Loaded(object sender, RoutedEventArgs e)
		{
			oMediaPlayer.MediaOpened += oMediaPlayer_MediaOpened;
			oMediaPlayer.MediaEnded += oMediaPlayer_MediaEnded;
			oMediaPlayer.MediaFailed += oMediaPlayer_MediaFailed;
			oMediaPlayer.CurrentStateChanged += oMediaPlayer_CurrentStateChanged;

			//For support Background Audio
			//Suspended 모드에서 실행되는 이벤트.
			MediaControl.PlayPressed += MediaControl_PlayPressed;
			MediaControl.PausePressed += MediaControl_PausePressed;
			MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
			MediaControl.StopPressed += MediaControl_StopPressed;
			MediaControl.NextTrackPressed += MediaControl_NextTrackPressed;
			MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed;

			//Play Slider 에서 표기되는 시간.
			PlaySlider.ValueChanged += timelineSlider_ValueChanged;

			PointerEventHandler pointerpressedhandler = new PointerEventHandler(slider_PointerEntered);
			PlaySlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, true);

			PointerEventHandler pointerreleasedhandler = new PointerEventHandler(slider_PointerCaptureLost);
			PlaySlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, true);

			//Play Slider 값 변경시 나타나는 Tool Tip
			PlaySlider.ThumbToolTipValueConverter = new ThumbToolTipValueConverter(); //Tool Tip
		}
		#endregion

		#region { Button Event }
		private void PlayerEventSet()
		{
			//List 에서 앞에있는 Music 실행
			btn_Previous.Tapped += btn_Previous_Tapped;
			btn_Play.Tapped += btn_Play_Tapped;
			btn_Pause.Tapped += btn_Pause_Tapped;
			//List 에서 뒤에있는 Music 실행
			btn_Next.Tapped += btn_Next_Tapped;
		}

		void btn_Previous_Tapped(object sender, TappedRoutedEventArgs e)
		{
			if (oSelectedStorageFile != null)
			{
				int i = 0;
				foreach (var _listItem in ItemListView.Items)
				{
					if (((Kim.Item)_listItem).StorageFile == oSelectedStorageFile)
					{
						if (0 <= --i)
							SetMediaPlayer((Kim.Item)ItemListView.Items[i]);
						break;
					}
					i++;
				}
			}
		}
		void btn_Play_Tapped(object sender, TappedRoutedEventArgs e)
		{
			oMediaPlayer.Play();
		}
		void btn_Pause_Tapped(object sender, TappedRoutedEventArgs e)
		{
			oMediaPlayer.Pause();
		}
		void btn_Next_Tapped(object sender, TappedRoutedEventArgs e)
		{
			if (oSelectedStorageFile != null)
			{
				int i = 0;
				foreach (var _listItem in ItemListView.Items)
				{
					if (((Kim.Item)_listItem).StorageFile == oSelectedStorageFile)
					{
						if (ItemListView.Items.Count > ++i)
							SetMediaPlayer((Kim.Item)ItemListView.Items[i]);
						break;
					}
					i++;
				}
			}
		}
		#endregion

		#region { Background Audio Event }
		private void MediaControl_StopPressed(object sender, object e)
		{
			oMediaPlayer.Stop();
		}

		async private void MediaControl_PlayPauseTogglePressed(object sender, object e)
		{
			await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
			{
				if (oMediaPlayer.CurrentState == MediaElementState.Playing)
				{
					oMediaPlayer.Pause();
				}
				else
				{
					oMediaPlayer.Play();
				}
			});
		}

		private void MediaControl_PausePressed(object sender, object e)
		{
			oMediaPlayer.Pause();
		}

		private void MediaControl_PlayPressed(object sender, object e)
		{
			oMediaPlayer.Play();
		}

		void MediaControl_PreviousTrackPressed(object sender, object e)
		{
			//* 동작하지 않음 *
			//이전 음악 실행.
			btn_Previous_Tapped(null, null);
		}

		void MediaControl_NextTrackPressed(object sender, object e)
		{
			//* 동작하지 않음 *
			//다음 음악 실행.
			btn_Next_Tapped(null, null);
		}
		#endregion

		#region { oMediaPlayer Event }
		void oMediaPlayer_CurrentStateChanged(object sender, RoutedEventArgs e)
		{
			if (oMediaPlayer.CurrentState == MediaElementState.Playing)
			{
				if (_sliderpressed)
				{
					_timer.Stop();
				}
				else
				{
					_timer.Start();
				}
				MediaControl.IsPlaying = true;

				btn_Pause.Visibility = Windows.UI.Xaml.Visibility.Visible;
				btn_Play.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
			}
			else
			{
				btn_Pause.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
				btn_Play.Visibility = Windows.UI.Xaml.Visibility.Visible;
			}

			if (oMediaPlayer.CurrentState == MediaElementState.Paused)
			{
				_timer.Stop();
				MediaControl.IsPlaying = false;
			}

			if (oMediaPlayer.CurrentState == MediaElementState.Stopped)
			{
				_timer.Stop();
				PlaySlider.Value = 0;
				MediaControl.IsPlaying = false;
			}
		}

		void oMediaPlayer_MediaFailed(object sender, ExceptionRoutedEventArgs e)
		{
		}

		void oMediaPlayer_MediaEnded(object sender, RoutedEventArgs e)
		{
		}

		void oMediaPlayer_MediaOpened(object sender, RoutedEventArgs e)
		{
			double absvalue = (int)Math.Round(oMediaPlayer.NaturalDuration.TimeSpan.TotalSeconds, MidpointRounding.AwayFromZero);
			PlaySlider.Maximum = absvalue;
			PlaySlider.StepFrequency = stepfrequency;
			tb_StartTime.Text = string.Format(strStringFormat, 0, 0);
			tb_EndTime.Text = string.Format(strStringFormat, Math.Floor(absvalue / 60), Math.Floor(absvalue % 60));
			SetTimer();
		}
		#endregion

		#region { timer bar }
		void slider_PointerEntered(object sender, PointerRoutedEventArgs e)
		{
			//System.Diagnostics.Debug.WriteLine("Pointer entered event fired");
			_sliderpressed = true;
		}

		void slider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
		{
			//System.Diagnostics.Debug.WriteLine("Pointer capture lost event fired");
			//System.Diagnostics.Debug.WriteLine("Slider value at capture lost {0}", PlaySlider.Value);
			//myMediaElement.PlaybackRate = 1;
			oMediaPlayer.Position = TimeSpan.FromSeconds(PlaySlider.Value);
			_sliderpressed = false;
		}

		void timelineSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
		{
			//System.Diagnostics.Debug.WriteLine("Slider old value = {0} new value = {1}.", e.OldValue, e.NewValue);
			if (!_sliderpressed)
			{
				oMediaPlayer.Position = TimeSpan.FromSeconds(e.NewValue);
			}
		}
		#endregion

		#region { timer function }
		//Player Slider 의 표기를 위한 Timer 설정
		private void SetTimer()
		{
			_timer = new DispatcherTimer();
			_timer.Interval = TimeSpan.FromSeconds(PlaySlider.StepFrequency);
			StartTimer();
		}

		private void StartTimer()
		{
			_timer.Tick += _timer_Tick;
			_timer.Start();
		}

		private void StopTimer()
		{
			_timer.Stop();
			_timer.Tick -= _timer_Tick;
		}

		private void _timer_Tick(object sender, object e)
		{
			if (!_sliderpressed)
			{
				double dTotalSeconds = oMediaPlayer.Position.TotalSeconds;
				PlaySlider.Value = dTotalSeconds;
				tb_StartTime.Text = string.Format(strStringFormat, Math.Floor(dTotalSeconds / 60), Math.Floor(dTotalSeconds % 60));
			}
		}
		#endregion

		/// <summary>
		/// oMediaPlayer Element에 file을 Set 한다.
		/// </summary>
		/// <param name="item"></param>
		async private void SetMediaPlayer(Kim.Item item)
		{
			oSelectedStorageFile = item.StorageFile;
			AlbumArtImage.Source = item.Image;
			oMediaPlayer.SetSource((await item.StorageFile.OpenAsync(FileAccessMode.Read)), "audio/mp3");
			tb_Artist.Text = "Artist\t:\t" + item.Artist;
			tb_Title.Text = "Title\t:\t" + item.Title;
			tb_Album.Text = "Album\t:\t" + item.Album;
		}
		#endregion

        /* 음악파일 열기를 클릭 했을 경우, 호출되는 함수: 리스트에 선택된 파일들을 보여주는 역활  */
		async private void PickAudioButton_Click(object sender, RoutedEventArgs e)
		{
			// 파일을 선택하기 전에 현재 앱이 unsnapped 상태인지 확인함(아닐경우 반환)
			if (!Kim.Constants.EnsureUnsnapped())
			{
				//this.OutputStatus.Text = "Unable to unsap the app.";
				return;
			}

            // mp3 파일들을 1개 이상으로 선택할수 있는 파일열기 창 호출
			FileOpenPicker picker = Kim.Constants.CreateFilePicker(Kim.Constants.audioExtensions);
			files = await picker.PickMultipleFilesAsync();

            // 선택한 파일이 한개 이상 존재시
			if (files != null && files.Count > 0)
			{
				Kim.ItemCollection _Collection = new Kim.ItemCollection();
				Kim.Item _TempItem = null;
				BitmapImage bitmapImage = null;

                // 선택된 파일 순서대로 foreach 돌림
				foreach (StorageFile file in files)
				{
					MusicProperties properties = await file.Properties.GetMusicPropertiesAsync();
					_TempItem = new Kim.Item();

                    // 파일 정보를 미리 선언한 Item 형식으로 _TempItem에 저장함
					/* 양수영, StorageFile Property 추가 */
					_TempItem.StorageFile = file;
					_TempItem.Title = properties.Title;
					_TempItem.Album = properties.Album;
					_TempItem.Artist = properties.Artist;

                    const ThumbnailMode thumbnailMode = ThumbnailMode.MusicView;
					const uint size = 100;

                    // 파일의 썸네일 정보를 가져옴
					using (StorageItemThumbnail thumbnail = await file.GetThumbnailAsync(thumbnailMode, size))
					{
						// 썸네일 형식의 이미지 존재시 해당 이미지 정보를 _TempItem에 저장함
                        bitmapImage = new BitmapImage();

                        // 썸네일 존재시
						if (thumbnail != null && thumbnail.Type == ThumbnailType.Image)
						{
							bitmapImage.SetSource(thumbnail);
							_TempItem.Image = bitmapImage;
						}
                        // 썸네일 미 존재시
						else
						{
                            _TempItem.Image = new BitmapImage(new Uri(new Uri("ms-appx:///"), "Assets/music.jpg"));
						}
					}

                    // Collection에 현재 파일 정보 추가
					_Collection.Add(_TempItem);

				}

                // List ItemsSource에 파일정보들이 포함된 Collection 지정
				ItemListView.ItemsSource = _Collection;
			}
			else
			{
				//this.OutputStatus.Text = "No files picked.";
			}
		}

        // 리스트에서 하나의 item을 선택할 경우 호출됨
		async void ListItemClickHandler(object sender, ItemClickEventArgs e)
		{
			Kim.Item _item = e.ClickedItem as Kim.Item;
			//this.OutputStatus.Text = _item.Title + "가 선택되었습니다.";

			SetMediaPlayer(_item); //Player Set
			if (!string.IsNullOrEmpty(_item.Artist))
			{
				var NewsList = await News.INSTANCE.GetNews(_item.Artist, SEARCHENGINE.All);
				this.lv_news.ItemsSource = NewsList;
			}
		}

		private object RowSpan(int i)
		{
			if (i == 0)
				return 3;
			if (i == 4)
				return 2;
			return 1;
		}

		private object ColSpan(int i)
		{
			if (i == 0)
				return 3;
			if (i == 4)
				return 2;
			return 1;
		}

		/// <summary>
		/// 이 페이지가 프레임에 표시되려고 할 때 호출됩니다.
		/// </summary>
		/// <param name="e">페이지에 도달한 방법을 설명하는 이벤트 데이터입니다. Parameter
		/// 속성은 일반적으로 페이지를 구성하는 데 사용됩니다.</param>
		protected override void OnNavigatedTo(NavigationEventArgs e)
		{
		}

		private void TextBlock_Tapped_1(object sender, TappedRoutedEventArgs e)
		{

		}

        private void lv_news_ItemClick_1(object sender, ItemClickEventArgs e)
        {
            NewsItem ni = e.ClickedItem as NewsItem;
            //PopupOpen(ni._link);
            BrowserOpen(ni._link);
        }

        async void BrowserOpen(string url)
        {
            var uri = new Uri(url);                        
            var success = await Windows.System.Launcher.LaunchUriAsync(uri);
            if (success)
            {
                
            }
            else
            {
                
            }
        }

        void PopupOpen(string msg)
        {
            Popup popup = new Popup();
            StackPanel panelHelp = new StackPanel();
            panelHelp.Background = new SolidColorBrush(Colors.Gray);
            panelHelp.Width = 700;
            panelHelp.Height = 100;
            Border border = new Border();
            border.BorderBrush = new SolidColorBrush(Colors.White);
            border.BorderThickness = new Thickness(3.0);

            TextBlock textblockHelp = new TextBlock();
            textblockHelp.FontSize = 25;
            textblockHelp.Foreground = new SolidColorBrush(Colors.White);
            textblockHelp.TextWrapping = TextWrapping.Wrap;
            textblockHelp.Text = msg;
            textblockHelp.Margin = new Thickness(5.0);
            panelHelp.Children.Add(textblockHelp);
            border.Child = panelHelp;
            popup.Child = border;            // 팝업을 보여줄 위치 지정 
            popup.VerticalOffset = 200;
            popup.HorizontalOffset = 85;
            // 팝업 Show 
            popup.IsOpen = true;
        }
	}

	#region { Player 에서 사용되는 Tooltip 변경 }
	public class ThumbToolTipValueConverter : IValueConverter
	{
		private string strStringFormat = "{0:00}:{1:00}";
		/// <summary>
		/// 
		/// </summary>
		public object Convert(object value, Type targetType, object parameter, string language)
		{
			if (value == null)
				return string.Format(strStringFormat, 0, 0);
			// ...
			double val = (double)value;
			return string.Format(strStringFormat, Math.Floor(val / 60), Math.Floor(val % 60));
		}
		/// <summary>
		/// 
		/// </summary>
		public object ConvertBack(object value, Type targetType, object parameter, string language)
		{
			throw new Exception();
		}
	}
	#endregion
}
